home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr40 / x1j4_src.zip / L2C.C < prev    next >
Text File  |  1995-01-21  |  44KB  |  896 lines

  1. /**************************************************************************\
  2. *                                                                          *
  3. *                                                                          *
  4. *    *****                      *****                                      *
  5. *      *****                  *****                                        *
  6. *        *****              *****                                          *
  7. *          *****          *****                                            *
  8. *            *****      *****                                              *
  9. *              *****  *****                                                *
  10. *            *****      *****                                              *
  11. *          *****          *****          The Firmware. The Net.            *
  12. *        *****              *****        Portable. Compatible.             *
  13. *      *****                  *****      Public Domain.                    *
  14. *    *****                      *****    By NORD><LINK.                    *
  15. *                                                                          *
  16. *                                                                          *
  17. *                                                                          *
  18. *    L2C.C   -   Level 2, Teil 3                                           *
  19. *                                                                          *
  20. *    angelegt:      DC4OX                                                  *
  21. *    modifiziert:                                                          *
  22. *                                                                          *
  23. *            G8KBB April 1991 - use of register keywork to compress code   *
  24. *                               condition include of cpyfb for KISS use    *
  25. *                  Nov 1991 - accumulate stats on certain packets sent     *
  26. *                  May 1993 - add non portable compare() function          *
  27. * Add support for meters and additional alias handling                     *
  28. *                                                                          *
  29. * September 1993 - released as TheNet X-1J                                 *
  30. *                                                                          *
  31. * add portflush support                                                    *
  32. * add various speedups                                                     *
  33. *                                                                          *
  34. * Released as TheNet X-1J release 4, January 1995                          *
  35. \**************************************************************************/
  36.  
  37.  
  38.  
  39.  
  40.  
  41. /*                                                             Includes   */
  42. /**************************************************************************/
  43.  
  44. #include "all.h"         /* allgemeine Festlegungen                       */
  45. #include "tntyp.h"       /* Festlegungen/Datenstrukturen fuer den Level 2 */
  46. #include "l2s.h"         /* Zugriff auf die State-Tabellen                */
  47. #include "l2ext.h"       /* globale Variable / nicht int-Funktionen       */
  48.  
  49.  
  50.  
  51.  
  52.  
  53. /**************************************************************************\
  54. *                                                                          *
  55. * action      :  Zustandsuebergangsfunktionen der Level-2-Statetable       *
  56. *                (x.../t...), Level-2-Timer setzen/aufloesen (setT./clrT.) *
  57. *                und Utilities fuer diese Funktionen.                      *
  58. *                                                                          *
  59. *   t2rrr()   -  Timer 2 setzen, nach Ablauf RR als Response zu senden     *
  60. *   t2rnrr()  -  Timer 2 setzen, nach Ablauf RNR als Response zu senden    *
  61. *   t2rejr()  -  Timer 2 setzen, nach Ablauf REJ als Response zu senden    *
  62. *                                                                          *
  63. *   xnull()   -  nichts tun                                                *
  64. *                                                                          *
  65. *   xrrc()    -  RR als Command senden                                     *
  66. *   xrrr()    -  RR als Response senden                                    *
  67. *   xrnrc()   -  RNR als Command senden                                    *
  68. *   xrnrr()   -  RNR als Response senden                                   *
  69. *   xrejr()   -  REJ als Response senden                                   *
  70. *                                                                          *
  71. *   xdm()     -  DM senden                                                 *
  72. *   xua()     -  UA senden                                                 *
  73. *   xsabm()   -  SABM senden                                               *
  74. *   xdisc()   -  DISC senden                                               *
  75. *                                                                          *
  76. *   xfrmr()   -  FRMR senden (-> L2E.C)                                    *
  77. *                                                                          *
  78. *   setT1()   -  Timer 1 setzen und Timer 3 loeschen                       *
  79. *   clrT1()   -  Timer 1 und tries loeschen, Timer 3 setzen                *
  80. *   setT2()   -  Timer 2 und nach Ablauf zu sendenden Frametyp setzen      *
  81. *   clrT2()   -  Timer 2 und nach Ablauf zu sendenden Frametyp loeschen    *
  82. *   setT3()   -  Timer 3 setzen, wenn Version 2 Protokoll benutzt wird     *
  83. *   clrT3()   -  Timer 3 loeschen                                          *
  84. *                                                                          *
  85. *   sendS()   -  Supervisory-Frame fuer Sendung aufbauen, Timer 2          *
  86. *                loeschen, Frame senden                                    *
  87. *   sdfrmr()  -  FRMR-Frame fuer Sendung aufbauen und senden (-> L2E.C)    *
  88. *                                                                          *
  89. \**************************************************************************/
  90.  
  91. VOID t2rrr()  { setT2(L2CRR);                                              }
  92.  
  93. VOID t2rnrr() { setT2(L2CRNR);                                             }
  94.  
  95. VOID t2rejr() { setT2(L2CREJ);                                             }
  96.  
  97. VOID setT1()  { lnkpoi->T1 = lnkpoi->initT1 + random(); clrT3();           }
  98.  
  99. VOID clrT1()  { lnkpoi->T1 = lnkpoi->tries = 0; setT3();                   }
  100.  
  101. VOID setT2(Stype) char Stype;
  102.               { lnkpoi->RStype = Stype; lnkpoi->T2 = T2par;                }
  103.  
  104. VOID clrT2()  { lnkpoi->T2 = 0; lnkpoi->RStype = 0;                        }
  105.  
  106. VOID setT3()  { if (lnkpoi->V2link == YES) lnkpoi->T3 = T3par;             }
  107.  
  108. VOID clrT3()  { lnkpoi->T3 = 0;                                            }
  109.  
  110. VOID xnull()  {                                                            }
  111.  
  112. VOID xrrc()   { stxcfr(); xrrr();                                          }
  113.  
  114. VOID xrrr()   { sendS(L2CRR);                                              }
  115.  
  116. VOID xrnrc()  { stxcfr(); xrnrr();                                         }
  117.  
  118. VOID xrnrr()  { sendS(L2CRNR);
  119. #ifdef STATSCMD
  120.                 L2TXRNR[lnkpoi->liport & MAXPORTMASK]++;
  121. #endif
  122. }
  123.  
  124. VOID xrejr()  { sendS(L2CREJ);
  125. #ifdef STATSCMD
  126.                 L2TXREJ[lnkpoi->liport & MAXPORTMASK]++;
  127. #endif
  128. }
  129.  
  130. VOID sendS(control) char control;
  131.               { clrT2(); txfctl=setNR(control);
  132.                 sdl2fr(makfhd(!txfCR ? L2FUS : (L2FUS | L2FT1ST))); }
  133.  
  134. VOID xdm()    { txfctl = L2CDM; sdl2fr(makfhd(L2FUS));                     }
  135.  
  136. VOID xua()    { txfctl = L2CUA; sdl2fr(makfhd(L2FUS));                     }
  137.  
  138. VOID xsabm()  { stxcfr(); txfctl = L2CSABM; sdl2fr(makfhd(L2FUS|L2FT1ST)); }
  139.  
  140. VOID xdisc()  { stxcfr(); txfctl = L2CDISC; sdl2fr(makfhd(L2FUS|L2FT1ST)); }
  141.  
  142.  
  143.  
  144.  
  145.  
  146. /**************************************************************************\
  147. *                                                                          *
  148. * "set tx command frame"                                                   *
  149. *                                                                          *
  150. * TX-Frame-Adressierung setzen (siehe stxfad()) und Frame zum Kommando-    *
  151. * frame machen mit gesetztem Pollbit (txfCR,txfPF).                        *
  152. *                                                                          *
  153. \**************************************************************************/
  154.  
  155. VOID stxcfr()
  156.   {
  157.     stxfad();                           /* Adressierung                   */
  158.     txfCR = L2CCR;                      /* Command !                      */
  159.     txfPF = L2CPF;                      /* Pollbit !                      */
  160.   }
  161.  
  162.  
  163.  
  164.  
  165.  
  166. /**************************************************************************\
  167. *                                                                          *
  168. * "set tx frame address"                                                   *
  169. *                                                                          *
  170. * Adressierung des aktuellen Sendeframes (txfhdr, txfprt) setzen aus den   *
  171. * im aktuellen Linkblock (lnkpoi) gegebenen Parametern (srcid, destid,     *
  172. * viaidl, liport).                                                         *
  173. *                                                                          *
  174. \**************************************************************************/
  175.  
  176. VOID stxfad()
  177.   {
  178.     cpyid(txfhdr + L2IDLEN,lnkpoi->srcid);        /* von ...              */
  179.     cpyid(txfhdr,lnkpoi->dstid);                  /* nach ...             */
  180.     cpyidl(txfhdr + L2ILEN,lnkpoi->viaidl);       /* ueber ...            */
  181.     txfprt = lnkpoi->liport;                      /* auf Port ...         */
  182.   }
  183.  
  184.  
  185.  
  186.  
  187.  
  188. /**************************************************************************\
  189. *                                                                          *
  190. * "set NR"                                                                 *
  191. *                                                                          *
  192. * Im aktuellen Linkblock (lnkpoi) die zuletzt gesendete N(R) (ltxdNR) auf  *
  193. * V(R) (VR) setzen und Framecontrolbyte control fuer Frameaussendung mit   *
  194. * der N(R) versehen und zurueckgeben.                                      *
  195. *                                                                          *
  196. * Return :  control mit N(R) versehen                                      *
  197. *                                                                          *
  198. \**************************************************************************/
  199.  
  200. unsigned setNR(control)
  201.  
  202. char control;
  203.  
  204.   {
  205.     lnkpoi->ltxdNR = lnkpoi->VR;             /* neue N(R)                 */
  206.     return((lnkpoi->VR << 5) | control);     /* N(R) ins Kontrollfeld     */
  207.   }
  208.  
  209.  
  210.  
  211.  
  212.  
  213. /**************************************************************************\
  214. *                                                                          *
  215. * "send level 2 frame"                                                     *
  216. *                                                                          *
  217. * Framebuffer, auf dessen Kopf fbp zeigt, rewinden und in die dem Port     *
  218. * (l2port) entsprechende Level-2-Sendeframeliste einhaengen, wenn noch     *
  219. * genug Buffer im System frei sind. Andernfalls nicht senden, sondern      *
  220. * sofort in die Gesendet-Liste (stfl) einhaengen. Bei TheNet die           *
  221. * Sendeaktiviatetsvariable (istraf) des entsprechenden Ports setzen.       *
  222. *                                                                          *
  223. \**************************************************************************/
  224.  
  225. VOID sdl2fr(fbp)
  226. register MBHEAD *fbp;
  227.  
  228.   {
  229.     register unsigned port;                      /* Portnummer                     */
  230.     
  231.     port = fbp->l2port;                 /* Portnummer holen               */
  232.     if (nmbfre > 64)                    /* noch genug Buffer ?            */
  233.       {
  234. #ifdef STATSCMD
  235.         L2TXCNT[port & MAXPORTMASK]++;  /* bump tx count */
  236. #endif
  237. #ifdef PORTFLUSH
  238.         pending[port] = 1;
  239. #endif
  240.         rwndmb(fbp);                    /* ja   - Framebuffer rewinden    */
  241.         DIinc();                        /*        Listenkonsistenz !      */
  242.         relink(fbp,txl2fl[port].tail);  /*        Frame in Sendeliste     */
  243.         kicktx(port);                   /*        es ist was zu senden !  */
  244.         decEI();                        /*        Interrupts w. erlauben  */
  245.  
  246. #ifndef FIRMWARE
  247.         istraf[port] = YES;             /*        es ist Port-Traffic     */
  248. #endif
  249.  
  250.       }
  251.     else                                /* nein - Frame einfach sofort    */
  252.       relink(fbp,stfl.tail);            /*        als gesendet betrachten */
  253.   }
  254.  
  255.  
  256.  
  257.  
  258.  
  259. /**************************************************************************\
  260. *                                                                          *
  261. * "copy frame buffer"                                                      *
  262. *                                                                          *
  263. * Framebuffer, auf den fbp zeigt, komplett mit Inhalt kopieren. Dazu freie *
  264. * Buffer allokieren, Portnummer (l1port) wird kopiert, Bufferzeiger (mbbp) *
  265. * und Getcounter (mbgc) werden nicht kopiert, bleiben aber im Quellframe   *
  266. * erhalten.                                                                *
  267. *                                                                          *
  268. * Return :  Zeiger auf Kopf des kopierten Framebuffers                     *
  269. *                                                                          *
  270. \**************************************************************************/
  271.  
  272. /* #ifdef FIRMWARE */
  273. #ifdef INCLUDEcpyfb
  274.  
  275. MBHEAD *cpyfb(fbp)
  276. register MBHEAD *fbp;
  277.  
  278.   {
  279.     register char *savmbbp;                /* mbbp-Sicherung                 */
  280.     unsigned    savmbgc;                   /* mbgc-Sicherung                 */
  281.     register MBHEAD *newfbp;               /* Zeiger auf die Kopie           */
  282.     
  283.     savmbbp = fbp->mbbp;                /* mbbp sichern                   */
  284.     savmbgc = fbp->mbgc;                /* mbgc sichern                   */
  285.     rwndmb(fbp);                        /* Quellframe rewinden            */
  286.     newfbp = allocb();                  /* Kopf der Kopie allokieren      */
  287. #ifdef MODIFIED
  288.     mhtyp_copy( fbp, newfbp );
  289. #else
  290.     while (fbp->mbgc < fbp->mbpc)       /* Daten byteweise kopieren       */
  291.       putchr(getchr(fbp),newfbp);
  292. #endif
  293.     newfbp->l2port = fbp->l2port;       /* Portnummer kopieren            */
  294.     fbp->mbbp = savmbbp;                /* mbbp wieder auf alten Wert     */ 
  295.     fbp->mbgc = savmbgc;                /* mbgc wieder auf alten Wert     */
  296.     return (newfbp);                    /* Zeiger auf Kopf der Kopie      */
  297.   }
  298.  
  299. #endif
  300.  
  301.  
  302.  
  303.  
  304.  
  305. /**************************************************************************\
  306. *                                                                          *
  307. * "take frame head"                                                        *
  308. *                                                                          *
  309. * Adresskopf und Kontrollbyte des Frames aus dem Framebuffer, auf dessen   *
  310. * Kopf fbp zeigt, analysieren. Diese Funktion ist die erste, die auf ein   *
  311. * empfangenes Frame angewandt wird.                                        *
  312. *                                                                          *
  313. *                                                                          *
  314. * Folgende Parameter werden bei der Analyse gesetzt (siehe auch L2V.C) :   *
  315. *                                                                          *
  316. *    rxfhdr, rxfV2, rxfPF, rxfCR, rxfctl, rxfprt                           *
  317. *                                                                          *
  318. *                                                                          *
  319. * Folgende Parameter werden nach der Analyse gesetzt fuer ein moegliches   *
  320. * Antwortframe :                                                           *
  321. *                                                                          *
  322. *   txfhdr  = Quell- und Zielcall aus rxfhdr, aber vertauscht, plus        *
  323. *             reverse via-Liste aus rxfhdr                                 *
  324. *   txfV2   = rxfV2                                                        *
  325. *   txfPF   = rxfPF                                                        *
  326. *   txfCR   = 0, Response !                                                *
  327. *   txfprt  = rxfprt                                                       *
  328. *                                                                          *
  329. *                                                                          *
  330. * Return :  TRUE  - das Frame hat einen gueltigen AX.25-Framekopf          *
  331. *           FALSE - sonst                                                  *
  332. *                                                                          *
  333. \**************************************************************************/
  334.  
  335. BOOLEAN takfhd(fbp)
  336.  
  337. MBHEAD *fbp;
  338.  
  339.   {
  340.     register char *viap;                                   /* Zeiger in via-Liste  */
  341.     register char *source;                                 /* Quellzeiger Kopien   */
  342.     register char *dest;                                   /* Zielzeiger Kopien    */
  343.  
  344.     rwndmb(fbp);                                  /* Frame von vorne      */
  345.     if (    !getfid(rxfhdr,fbp)                   /* Zielcall holen       */
  346.          || ((rxfhdr[L2IDLEN - 1] & L2CEOA) != 0) /* (Ende nach 1. Call ?)*/
  347.          || !getfid(rxfhdr + L2IDLEN,fbp)         /* Quellcall holen      */
  348.        ) return (FALSE);                          /* ... schon Fehler     */
  349.     viap = rxfhdr + L2ILEN;                       /* ab hier via-Liste    */
  350.     if (!(rxfhdr[L2ILEN - 1] & L2CEOA))           /* via-Liste da ?       */
  351.       LOOP
  352.         {                                               /* alle via's     */
  353.           if (!getfid(viap,fbp)) return (FALSE);        /* Call holen     */
  354.           viap += L2IDLEN;                              /* naechstes Call */
  355.           if ((*(viap - 1) & L2CEOA) != 0) break;       /* Ende der Liste */
  356.           if (viap >= rxfhdr + L2AFLEN) return (FALSE); /* zu lange Liste */
  357.         }
  358.     *viap = '\0';                                       /* Listenende !   */
  359.     if (fbp->mbgc == fbp->mbpc) return (FALSE);         /* Frame zu kurz  */
  360.     rxfctl = getchr(fbp);                               /* Controlbyte    */
  361.  
  362.  
  363.     /* Protokollversion feststellen und danach C/R und P/F festlegen */
  364.  
  365.     if ( (rxfV2 = ((rxfhdr[L2IDLEN - 1] ^ rxfhdr[L2ILEN - 1]) & L2CCR) != 0)
  366.          == YES
  367.        )
  368.       {                                           /* nur Version 2 :      */
  369.         rxfCR = rxfhdr[L2IDLEN - 1] & L2CCR;      /*   Command/Response   */
  370.         rxfPF = rxfctl & L2CPF;                   /*   Poll/Final         */
  371.       }
  372.     else                                          /* Version 1 :          */
  373.       rxfPF = rxfCR = 0;                          /* P/F u. C/R sinnlos   */
  374.  
  375.     rxfctl &= ~L2CPF;                             /* P/F Control loeschen */
  376.     rxfprt = fbp->l2port;                         /* Portnummer holen     */
  377.  
  378. #ifdef METERS
  379.     rxfdev = fbp->rxdev;
  380.     siglev = fbp->sig_level;
  381. #endif
  382.  
  383.     /* Antwort-Sendeframeaufbau */
  384.  
  385.     txfCR = 0;                                    /* Response !           */
  386.     txfV2 = rxfV2;                                /* Version              */
  387.     txfPF = rxfPF;                                /* Poll/Final           */
  388.     txfprt = rxfprt;                              /* Portnummer           */
  389.     cpyid(txfhdr,rxfhdr + L2IDLEN);               /* TX-Ziel = RX-Quelle  */
  390.     cpyid(txfhdr + L2IDLEN,rxfhdr);               /* TX-Quelle = RX-Ziel  */
  391.     source = rxfhdr + L2ILEN;                     /* TX-Antwort-via-Liste */
  392.     dest = txfhdr + L2ILEN;                       /* ist, falls vorhanden */
  393.     {
  394.         while (*source != '\0') source += L2IDLEN;    /* reverse RX-via-Liste */
  395.         while (source != rxfhdr + L2ILEN)
  396.         {
  397.             source -= L2IDLEN;
  398.             cpyid(dest,source);
  399.             dest += L2IDLEN;
  400.           }
  401.     }
  402.     *dest = '\0';                                 /* Listenende !         */
  403.     return (TRUE);                                /* Frame soweit okay !  */
  404. }
  405.  
  406.  
  407.  
  408.  
  409.  
  410. /**************************************************************************\
  411. *                                                                          *
  412. * "get frame ID"                                                           *
  413. *                                                                          *
  414. * Die naechste ID nach dest (Call + SSID, SSID wie im Frame) holen aus dem *
  415. * Buffer (Call + SSID, beide wie im Frame), auf dessen Kopf mbhd zeigt.    *
  416. * Die geholte SSID enthaelt das End-Of-Address-Bit unveraendert.           *
  417. *                                                                          *
  418. * Return :  TRUE  - die naechste ID (Call + SSID) wurde richtig geholt     *
  419. *           FALSE - es hat sich ein Fehler ereignet                        *
  420. *                                                                          *
  421. \**************************************************************************/
  422.  
  423. BOOLEAN getfid(dest,mb)
  424. char     *dest;
  425. MBHEAD   *mb;
  426.   {
  427.     register char       c;                       /* aktuelles Zeichen aus Buffer   */
  428.     register unsigned   n;                       /* Zaehler Call-Laenge            */
  429.     register MBHEAD *mbhd = mb;
  430.  
  431.     if (mbhd->mbpc - mbhd->mbgc < L2IDLEN)        /* im Buffer nicht mehr */
  432.       return (FALSE);                             /* genug Bytes fuer ID  */
  433.     for (n = L2CALEN; n != 0; --n)                 /* Call byteweise holen */
  434.       {
  435.         if (((c = getchr(mbhd)) & L2CEOA) != 0)   /* Adressfeld zu frueh  */
  436.           return (FALSE);                         /* zuende               */
  437.         *dest++ = (c >> 1) & 0x7F;                /* Framecall -> ASCII   */
  438.       }
  439.     *dest = getchr(mbhd);               /* SSID holen, EOA bleibt         */
  440.     return (TRUE);
  441.   }
  442.  
  443.  
  444.  
  445.  
  446.  
  447. /**************************************************************************\
  448. *                                                                          *
  449. * "make frame head"                                                        *
  450. *                                                                          *
  451. * Neues Frame aufbauen aus den txf...-Parametern. Es werden neue Buffer    *
  452. * fuer das Frame allokiert, der aktuelle Linkblock (lnkpoi) wird           *
  453. * eingetragen und fflag fuer das Frameflag l2fflg.                         *
  454. *                                                                          *
  455. * Return :  Zeiger auf Framebufferkopf des neu erzeugten Frames            *
  456. *                                                                          *
  457. \**************************************************************************/
  458.  
  459. MBHEAD *makfhd(fflag)
  460.  
  461. unsigned fflag;
  462.  
  463.   {
  464.     register MBHEAD *fbp;                                  /* Zeiger auf Kopf      */
  465.     
  466.     if (txfV2 == YES)                             /* wenn Version 2 ...   */
  467.       {
  468.         txfhdr[L2IDLEN - 1] |= txfCR;             /* ... C-Bits setzen    */
  469.         txfhdr[L2ILEN - 1] |= txfCR ^ L2CCR;
  470.       }
  471.     putfid(txfhdr,fbp = allocb());                /* neuer Buffer, Ziel   */
  472.     putfid(txfhdr + L2IDLEN,fbp);                 /* Quellcall            */
  473.     putvia(txfhdr + L2ILEN,fbp);                  /* via-Liste            */
  474.     putchr(!txfV2 ? txfctl : txfctl | txfPF,fbp); /* Control + P/F        */
  475.     fbp->l2link = lnkpoi;                         /* Verweis Linkblock    */
  476.     fbp->type = 2;                                /* Level 2 !            */
  477.     fbp->l2fflg = fflag;                          /* Frameflag            */
  478.     fbp->l2port = txfprt;                         /* Portnummer           */
  479.     return (fbp);                                 /* Kopfzeiger zurueck   */
  480.   }
  481.  
  482.  
  483.  
  484.  
  485.  
  486. /**************************************************************************\
  487. *                                                                          *
  488. * "put via"                                                                *
  489. *                                                                          *
  490. * Nullterminierte via-Liste, auf die idl zeigt, in den Framebuffer, auf    *
  491. * dessen Kopf mbhd zeigt, uebertragen. Die Nullterminierung nicht ueber-   *
  492. * tragen, aber am Ende der via-Liste das letzte Zeichen der via-Liste mit  *
  493. * dem HDLC End-Of-Address-Bit uebertragen.                                 *
  494. *                                                                          *
  495. \**************************************************************************/
  496.  
  497. VOID putvia(idl,mbhd)
  498. register char     *idl;
  499. register MBHEAD   *mbhd;
  500.   {
  501.     while (*idl != '\0')                /* gesamte via-Liste in den       */
  502.       {                                 /* Framebuffer uebertragen        */
  503.         putfid(idl,mbhd);
  504.         idl += L2IDLEN;
  505.       }                                 /* dann                           */
  506.     *(mbhd->mbbp - 1) |= L2CEOA;        /* EoA direkt im Buffer setzen    */
  507.   }
  508.  
  509.  
  510.  
  511.  
  512.  
  513. /**************************************************************************\
  514. *                                                                          *
  515. * "put frame id"                                                           *
  516. *                                                                          *
  517. * ID (Call und SSID, SSID wie im Frame), auf die id zeigt, in den          *
  518. * Framebuffer, auf dessen Kopf mbhd zeigt, uebertragen. Dabei Call von     *
  519. * ASCII in Frameformat (1 Bit linksgeschoben) umwandeln.                   *
  520. *                                                                          *
  521. \**************************************************************************/
  522.  
  523. VOID putfid(id,mbhd)
  524. register char     *id;
  525. register MBHEAD   *mbhd;
  526.   {
  527.     register unsigned n;                         /* Zaehler Call-Laenge            */
  528.  
  529.     for (n = L2CALEN; n != 0; --n)       /* Call uebertragen in Buffer,    */
  530.       putchr(*id++ << 1,mbhd);          /* 1 Bit linksgeschoben           */
  531.     putchr(*id,mbhd);                   /* SSID unveraendert uebertragen  */
  532.   }
  533.  
  534.  
  535.  
  536.  
  537.  
  538. /**************************************************************************\
  539. *                                                                          *
  540. * "is to me"                                                               *
  541. *                                                                          *
  542. * Pruefen, ob die ID (Call + SSID, SSID wie im Frame), auf die id zeigt,   *
  543. * mit der ID der eigenen Station (myid) uebereinstimmt (SSID wird ohne     *
  544. * Steuerbits verglichen), oder ob das Call, auf das id zeigt, mit dem      *
  545. * symbolischen Namen (alias) der eigenen Station uebereinstimmt.           *
  546. *                                                                          *
  547. * Return :  TRUE  - myid stimmt mit id ueberein oder alias mit dem         *
  548. *                   call in id                                             *
  549. *           FALSE - sonst                                                  *
  550. *                                                                          *
  551. \**************************************************************************/
  552.  
  553. BOOLEAN istome(id)
  554. register char *id;
  555.  
  556.   {
  557.     return (cmpid(myid,id) || cmpcal(alias,id)
  558. #ifdef MODIFIED
  559.             ||
  560.             ( enaliases && ( cmpcal( bbsalias, id ) || cmpcal( hostalias, id )
  561.                              || cmpcal( dxcalias, id )))
  562. #endif
  563.            );
  564.   }
  565.  
  566.  
  567.  
  568.  
  569.  
  570. /**************************************************************************\
  571. *                                                                          *
  572. * "compare calls"                                                          *
  573. *                                                                          *
  574. * Calls miteinander vergleichen.                                           *
  575. *                                                                          *
  576. * Return :  TRUE  - die Calls stimmen ueberein                             *
  577. *           FALSE - die Calls stimmen nicht ueberein oder mindestens eins  *
  578. *                   der Calls beginnt mit einem Blank                      *
  579. *                                                                          *
  580. \**************************************************************************/
  581.  
  582. #ifdef PORTABLE
  583. BOOLEAN cmpcal(call1,call2)
  584. register char *call1;
  585. register char *call2;
  586.   {
  587.     register unsigned n;                                        /* Zaehler         */
  588.  
  589.     if ( *call2 == ' ' || *call1 == ' ')               /* 1. Zeich. ' ' ? */
  590.          return( NO );
  591. #ifdef PORTABLE
  592.     for (n = 0; n < L2CALEN; ++n)                      /* jedes Zeichen   */
  593.       if ( *call2++ != *call1++ )                      /* sonst gleich ?  */
  594.          return (NO);                                  /* nein            */
  595.     return (YES);                                      /* ja, alle gleich */
  596. #else
  597.     return( compare( call1, call2, L2CALEN ) );
  598. #endif
  599.   }
  600. #endif
  601.  
  602.  
  603.  
  604.  
  605. /**************************************************************************\
  606. *                                                                          *
  607. * "compare ID list"                                                        *
  608. *                                                                          *
  609. * Nullterminierte ID-Listen (Calls + SSID's, SSID wie im Frame)            *
  610. * miteinander vergleichen (SSID nur reine SSID 0-15 vergleichen ohne       *
  611. * Steuerbits).                                                             *
  612. *                                                                          *
  613. * Return :  TRUE  - die ID-Listen stimmen ueberein                         *
  614. *           FALSE - sonst                                                  *
  615. *                                                                          *
  616. \**************************************************************************/
  617.  
  618. BOOLEAN cmpidl(idl1,idl2)
  619.  
  620. register char *idl1;
  621. register char *idl2;
  622.  
  623.   {
  624.     while (*idl2 != '\0')                         /* bis Liste 2 zuende   */
  625.       {
  626.         if (!cmpid(idl1,idl2)) return (NO);       /* ID's vergleichen     */
  627.         idl2 += L2IDLEN;                          /* Zeiger auf naechste  */
  628.         idl1 += L2IDLEN;                          /* ID's                 */
  629.       }                                           /* Listen gleich, wenn  */
  630.     return (!*idl1);                              /* beide zuende         */
  631.   }
  632.  
  633.  
  634.  
  635.  
  636.  
  637. /**************************************************************************\
  638. *                                                                          *
  639. * "compare ID's"                                                           *
  640. *                                                                          *
  641. * ID's (Call + SSID, SSID wie im Frame) miteinander vergleichen (SSID nur  *
  642. * reine SSID 0-15 vergleichen ohne Steuerbits).                            *
  643. *                                                                          *
  644. * Return :  TRUE  - die ID's stimmen ueberein                              *
  645. *           FALSE - sonst                                                  *
  646. *                                                                          *
  647. \**************************************************************************/
  648.  
  649. #ifdef PORTABLE
  650. BOOLEAN cmpid(id1,id2)
  651. register char *id1;
  652. register char *id2;
  653.  
  654.   {
  655. #ifdef PORTABLE
  656.     register unsigned n;                                   /* Zaehler              */
  657.     
  658.     for (n = 0; n < L2CALEN; ++n)                 /* Calls vergleichen    */
  659.       if (*id2++ != *id1++) return (NO);
  660.     return ((*id2 & 0x1E) == (*id1 & 0x1E));      /* reine SSID vergl.    */
  661. #else
  662.     if( !compare( id1, id2, L2CALEN ) )
  663.       return( NO );
  664.     return ((id2[L2CALEN] & 0x1E) == (id1[L2CALEN] & 0x1E)); /* reine SSID vergl.    */
  665. #endif
  666.   }
  667. #endif
  668.  
  669.  
  670.  
  671.  
  672. /**************************************************************************\
  673. *                                                                          *
  674. * "copy ID list"                                                           *
  675. *                                                                          *
  676. * Nullterminierte ID-Liste (Calls + SSID's, SSID wie im Frame) von source  *
  677. * nach dest kopieren, Zielliste mit '\0' abschliessen.                     *
  678. *                                                                          *
  679. \**************************************************************************/
  680.  
  681. VOID cpyidl(dest,source)
  682. register char *dest;
  683. register char *source;
  684.  
  685.   {
  686.     while (*source != '\0')             /* solange Liste nicht zuende     */
  687.       {
  688.         cpyid(dest,source);             /* ID kopieren                    */
  689.         source += L2IDLEN;              /* Zeiger um eine ID-Laenge       */
  690.         dest += L2IDLEN;                /* weiter                         */
  691.       }
  692.     *dest = '\0';                       /* Zielliste abschliessen         */
  693.   }
  694.  
  695.  
  696.  
  697.  
  698.  
  699. /**************************************************************************\
  700. *                                                                          *
  701. * "copy ID"                                                                *
  702. *                                                                          *
  703. * Komplette ID (Call + SSID, SSID wie im Frame), auf die source zeigt,     *
  704. * nach dest kopieren. In der kopierten SSID das End-Of-Address-Bit und das *
  705. * Command/Response/Has-Been-Repeated-Bit loeschen.                         *
  706. *                                                                          *
  707. \**************************************************************************/
  708.  
  709. VOID cpyid(dest,source)
  710. register char *source;
  711. register char *dest;
  712.  
  713.   {
  714. #ifdef PORTABLE
  715.     register unsigned n;                           /* Laengenzaehler               */
  716.  
  717.     for (n = 0; n < L2CALEN; ++n)         /* Call kopieren                */
  718.       *dest++ = *source++;
  719.     *dest = *source & ~(L2CEOA | L2CCR);  /* SSID kopieren, Bits loeschen */
  720. #else
  721.     memcpy( dest, source, L2CALEN+1 );
  722.     dest[L2CALEN] &= ~(L2CEOA | L2CCR);  /* SSID kopieren, Bits loeschen */
  723. #endif
  724.   }
  725.  
  726.  
  727.  
  728.  
  729.  
  730. /**************************************************************************\
  731. *                                                                          *
  732. * "deallocate message list"                                                *
  733. *                                                                          *
  734. * Komplette Messageliste, auf deren Listenkopf mlp zeigt, deallokieren.    *
  735. * D.h. alle Messagespeicher (jeweils Kopf und daran haengende Datenbuffer) *
  736. * deallokieren.                                                            *
  737. *                                                                          *
  738. *                                                                          *
  739. *            +--------+    +--------+               +--------+             *
  740. *    mlp --->| head   |--->|        |--->       --->|        |---> mlp     *
  741. *            +--------+    +--------+      ...      +--------+             *
  742. *      b <---| tail   |<---|        |<---       <---|        |<--- b       *
  743. *            +--------+    +--------+               +--------+             *
  744. *                          |        |---> \         |        |---> \       *
  745. *                          +        +      |        +        +      |      *
  746. *                          |        |<--- /|        |        |<--- /|      *
  747. *                          +--------+      |        +--------+      |      *
  748. *                          |        |      |        |        |      |      *
  749. *                                          |                        |      *
  750. *      deallokieren                        |------------------------|      *
  751. *                                            siehe unten dealmb()          *
  752. *                                                                          *
  753. \**************************************************************************/
  754.  
  755. VOID dealml(mlp)
  756. register LEHEAD *mlp;
  757.  
  758.   {
  759.     register MBHEAD *bp;                         /* Zeiger auf Messagebufferhead   */
  760.     
  761.     LOOP                                /* fuer alle Messagebufferheads   */
  762.       {                                 /* in Messagespeicherliste :      */
  763.         DIinc();                        /* Listenkonsistenz !             */
  764.         bp = mlp->nextle;               /* Zeiger auf naechsten Msgbhead  */
  765.         decEI();                        /* Interrupts wieder erlauben     */
  766.         if (mlp == bp) break;           /* Schwanz beisst Kopf -> fertig  */
  767.         dealmb(unlink(bp));             /* sonst Messagespeicher deallok. */
  768.       }
  769.   }
  770.  
  771.  
  772.  
  773.  
  774.  
  775. /**************************************************************************\
  776. *                                                                          *
  777. * "deallocate message buffer"                                              *
  778. *                                                                          *
  779. * Einen kompletten Messagespeicher, auf dessen Kopf mbhd zeigt,            *
  780. * deallokieren, d.h. sowohl den Messagebufferhead als auch alle an dessen  *
  781. * Messagebufferliste haengende Datenbuffer deallokieren.                   *
  782. *                                                                          *
  783. *                                                                          *
  784. *            +--------+           deallokieren                             *
  785. *    mbhd -->|        |                                                    *
  786. *            +--------+                                                    *
  787. *            |        |                                                    *
  788. *            +--------+      +--------+                +--------+          *
  789. *      a --->|        |----->|        |--->        --->|        |---> a    *
  790. *            +  mbl   +      +--------+      ...       +--------+          *
  791. *      b <---|        |<-----|        |<---        <---|        |<--- b    *
  792. *            +--------+      +--------+                +--------+          *
  793. *            |        |      |        |                |        |          *
  794. *                                                                          *
  795. \**************************************************************************/
  796.  
  797. VOID dealmb(mbhd)
  798. register MBHEAD *mbhd;
  799.  
  800.   {
  801.     register MB *bp;                                       /* Datenbufferzeiger    */
  802.     
  803.     while ((bp = mbhd->mbl.head) != &mbhd->mbl)   /* alle Datenbuffer     */
  804.       dealoc(unlink(bp));
  805.     dealoc(mbhd);                                 /* am Ende den Kopf     */
  806.   }
  807.  
  808.  
  809.  
  810.  
  811.  
  812. /**************************************************************************\
  813. *                                                                          *
  814. * "deallocate"                                                             *
  815. *                                                                          *
  816. * Buffer, auf den bp zeigt, initialisieren als neuen Messagebufferhead     *
  817. * (rwndmb()) und deallokieren, d.h. in die Freiliste freel einhaengen und  *
  818. * den Freibufferzaehler nmbfre inkrementieren.                             *
  819. *                                                                          *
  820. *                                                                          *
  821. *            +--------+                                                    *
  822. *     bp --->|        |         deallokieren                               *
  823. *            +--------+                                                    *
  824. *            |        |                                                    *
  825. *            +--------+                                                    *
  826. *            |        |                                                    *
  827. *                                                                          *
  828. \**************************************************************************/
  829.  
  830. VOID dealoc(bp)
  831. register MBHEAD *bp;
  832.  
  833.   {
  834.       bp->mbl.head                      /* als Messagehead initialisieren */
  835.     = bp->mbl.tail                      /*   Bufferlistenkopf             */
  836.     = &bp->mbl;                         /*   initialisieren               */
  837.     bp->mbpc = 0;                       /*   Message leer                 */
  838.     rwndmb(bp);                         /*   Rest initialisieren          */
  839.     DIinc();                            /* Listenkonsistenz !             */
  840.     relink(bp,freel.tail);              /* Buffer an Freiliste anhaengen  */
  841.     ++nmbfre;                           /* 1 Freibuffer mehr              */
  842.     decEI();                            /* Interrupts wieder erlauben     */
  843.   }
  844.  
  845.  
  846.  
  847.  
  848.  
  849. /**************************************************************************\
  850. *                                                                          *
  851. * "initialize head"                                                        *
  852. *                                                                          *
  853. * Listenkopf, auf den hd zeigt, initialisieren :                           *
  854. *                                                                          *
  855. *                                                                          *
  856. *                                              +----------------------+    *
  857. *                                              | +------------------+ |    *
  858. *                                              | |                  | |    *
  859. *            +--------+                        v v   +--------+     | |    *
  860. *     hd --->|        |         ->        hd ------->|        |-----+ |    *
  861. *            +--------+                              +--------+       |    *
  862. *            |        |                              |        |-------+    *
  863. *            +--------+                              +--------+            *
  864. *            |        |                              |        |            *
  865. *                                                                          *
  866. \**************************************************************************/
  867.  
  868. VOID inithd(hd)
  869. register LHEAD *hd;
  870.  
  871.   {
  872.     hd->head = hd->tail = hd;
  873.   }
  874.  
  875.  
  876.  
  877.  
  878.  
  879. /**************************************************************************\
  880. *                                                                          *
  881. * "level 2 to level x"                                                     *
  882. *                                                                          *
  883. * Meldung msg (L2M...) an Layer 3 und hoehere Layer weitergeben.           *
  884. *                                                                          *
  885. \**************************************************************************/
  886.  
  887. VOID l2tolx(msg)
  888. register unsigned msg;
  889.  
  890.   {
  891.     l2tol3(msg);                        /* Layer 2  ->  Layer 3           */
  892.     l2tol7(msg,lnkpoi,2);               /* Layer 2  ->  Layer 7           */
  893.   }
  894.  
  895. /* Ende von L2C.C */
  896.